package org.dylan.common.dao.hibernate;

import java.io.Serializable;
import java.util.List;

import javacommon.xsqlbuilder.XsqlBuilder.XsqlFilterResult;

import org.dylan.common.dao.PagingDao;
import org.dylan.common.paging.PageData;
import org.dylan.common.paging.PageRequest;
import org.dylan.common.util.XSqlUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Projections;
import org.springframework.stereotype.Repository;

@Repository
public class HibernatePagingDao<T, PK extends Serializable> extends
		HibernateBaseDao<T, PK> implements PagingDao<T, PK> {

	@Override
	public PageData<T> findByPage(PageRequest pageRequest) {
		PageData<T> pageData = new PageData<T>(pageRequest.limit());
		if (pageRequest.unLimit()) {
			// 不需要进行分页
			List<T> result = super.findByParam(pageRequest);
			pageData.setResult(result);
			pageData.setTotalCount(result == null ? 0 : result.size());
		} else {//进行分页计算
			Criteria crit = createCriteria(pageRequest, false);
			int totalCount = ((Number) crit.setProjection(
					Projections.rowCount()).uniqueResult()).intValue();
			pageData.setTotalCount(totalCount);
			crit = createCriteria(pageRequest);
			crit.setFirstResult(pageRequest.start());
			crit.setMaxResults(pageRequest.limit());
			crit.setProjection(null);
			pageData.setResult(crit.list());
		}
		return pageData;
	}
	
	public <E> PageData<E> pageQueryByHQL(final String hql, final PageRequest pageRequest) {
		final String countHql = buildCountHQL(hql);
		return pageQueryByHQL(hql, countHql, pageRequest);
	}
	
	/**
	 * 由数据查询的hql构建出数据统计使用的hql语句
	 * @param hql
	 * @return
	 */
	protected String buildCountHQL(String hql){
		return "select count(*) "
				+ XSqlUtils.removeSelect(XSqlUtils.removeFetchKeyword((hql)));
	}
	
	public <E> PageData<E> pageQueryByHQL(final String hql, String countHql,
			final PageRequest pageRequest) {
		if(pageRequest.unLimit()){
			//不需要进行数据分页
			PageData<E> pageData = new PageData<E>(pageRequest.limit());
			List<E> datas = super.findByHQL(hql,pageRequest);
			pageData.setResult(datas);
			pageData.setTotalCount(datas == null ? 0 : datas.size());
			return pageData;
		}
		//执行数据分页的查询
		XsqlFilterResult queryXsqlResult = XSqlUtils.buildXsqlFilterResult(getXsqlBuilder(), hql, pageRequest);

		XsqlFilterResult countQueryXsqlResult = XSqlUtils.buildXsqlFilterResult(getXsqlBuilder(), countHql, pageRequest);

		return pageQueryByHQL(pageRequest, queryXsqlResult, countQueryXsqlResult);
	}

	private <T> PageData<T> pageQueryByHQL(final PageRequest pageRequest,
			final XsqlFilterResult queryXsqlResult,
			final XsqlFilterResult countQueryXsqlResult) {
		Session session = getSession();
		Query query = setQueryParameters(
				session.createQuery(queryXsqlResult.getXsql()),
				queryXsqlResult.getAcceptedFilters());
		Query countQuery = setQueryParameters(session
				.createQuery(XSqlUtils.removeOrders(countQueryXsqlResult
						.getXsql())), countQueryXsqlResult
				.getAcceptedFilters());
		int total = ((Number)countQuery.uniqueResult()).intValue();
		PageData<T> pageData = new PageData<T>(pageRequest.limit());
		pageData.setTotalCount(total);
		if(total == 0){
			return pageData;
		}
		query.setFirstResult(pageRequest.start());
		query.setMaxResults(pageRequest.limit());
		pageData.setResult(query.list());
		return pageData;
	}
	
}
